#include <iostream>
#include <string.h>
#include <utility>
#include <assert.h>
using namespace std;

namespace fuh{
    class string{
        public:
        typedef char* iterator;
        typedef const char* cosnt_iterator;

            
            iterator begin()
            {
                return _str;
            }
            iterator end()
            {
                return _str+_size;
            }
            iterator begin()const
            {
                return _str;
            }
            iterator end()const
            {
                return _str+_size;
            }
            string(string&& s)
            :_size(0),
            _capacity(0),
            _str(new char[1]{0})
            {
                swap(s);
            }
            string(const string& s)
            :_size(0),
            _capacity(0),
            _str(new char[1]{0})
            {
                string tmp(s._str);
                swap(tmp);
            }
            string(const char* str = "")
            :_size(strlen(str))
            ,_capacity(_size+1)
            {
                _str = new char[_capacity+1];//留给\0
                strcpy(_str,str);
            }
            ~string()
            {
                _size = 0;
                _capacity = 0;
                delete []_str;
            }

            char& operator[](size_t pos)
            {
                assert(pos<_size);
                return _str[pos];
            }
            const char& operator[](size_t pos)const
            {
                assert(pos<_size);
                return _str[pos];
            }
            size_t size()const
            {
                return _size;
            }
            size_t capacity()const
            {
                return _capacity;
            }
            void push_back(char ch)
            {
                if(_size == _capacity)
                {
                    reserve(_capacity==0 ? 4:_capacity*2);
                }
                _str[_size++] = ch;
                _str[_size] = 0;
            }
            void reserve(size_t n)
            {
                _capacity= _capacity==0 ? 4:_capacity*2;
                while(n>_capacity)
                {
                    _capacity*=2;
                } 
                char* t = new char[_capacity+1];//存n+1放下\0
                    strcpy(t,_str);//会拷贝\0给
                    delete []_str;
                    _str = t;
            }
            void append(const string& s)
            {
                size_t n = s.size()+_size;
                if(n>_capacity)
                {
                    reserve(n);
                }
                strcpy(_str+_size,s._str);
                _size = n;
            }
            void append(const char* s)
            {
                size_t n = strlen(s)+_size;
                if(n>_capacity)
                {
                    reserve(n);
                }
                strcpy(_str+_size,s);
                _size = n;
                _str[n] = 0;
            }
            string& operator+=(const string& s)
            {
                append(s);
                return *this;
            }
            string& operator+=(const char* s)
            {
                append(s);
                return *this;
            }
            string& operator+=(const char s)
            {
                push_back(s);
                return *this;
            }
            void insert(size_t pos,const char ch)
            {
                assert (pos<=_size);
                if(_size == _capacity)
                {
                    reserve(_capacity==0 ? 4:_capacity*2);
                }
                size_t end = _size++;
                for(;end>pos;end--)
                {
                    _str[end] = _str[end-1];
                }
                _str[pos] = ch;
                _str[_size] = 0;
                
            }
            void insert(size_t pos,const char* s)
            {
                if(s==nullptr)
                {
                    return ;
                }
                assert (pos<=_size );
                size_t sz = _size +strlen(s);
                if(sz>_capacity)
                {
                    reserve(sz);
                }
                size_t end = _size;
                _size += strlen(s);
                _str[_size] = 0;//单独处理\0
                int end_pos = _size -1;
                for(;end>pos;end--,end_pos--)
                {
                    _str[end_pos] = _str[end-1];
                }
                for(int i=0;i<strlen(s);)
                {
                    _str[pos++] = s[i++];
                }
                print();
            }
            void erase(size_t pos,size_t lens = npos)
            {
                assert (pos<=_size);
                if(lens>=_size-pos)
                {
                    _size = pos;
                    _str[_size] = 0;
                    return ;
                }
                int end = lens+pos;
                int t = _size - lens;
                for(;end<_size;end)
                {
                    _str[pos++] = _str[end++];
                }
                _size = t;
                _str[_size] = 0;
            }
            void swap(string & s)
            {
                std::swap(_str,s._str);
                std::swap(_capacity,s._capacity);
                std::swap(_size,s._size);
            }
            string& operator=(const string& s)
            {
                if(this != &s)
                {
                    string tmp(s._str);
                    swap(tmp);
                }
                return *this;
            }
            string& operator=(string&& s)
            {
                swap(s);
                return *this;
            }
            // string& operator=(string tmp)//当传值的时候，给这里待用一次拷贝构造，就不用重复上，但是如果自己给自己赋值就不如上面
            // //且如果出现自己给自己赋值，那么里面地址就会改变，但是考虑一般情况，几乎不存在自己给自己赋值
            // {
            //     swap(tmp);
            //     return *this;
            // }
            bool operator<(const string & s)const 
            {
                return strcmp(_str,s._str)<0;
            }
            bool operator==(const string & s)const 
            {
                return strcmp(_str,s._str)==0;
            }
            bool operator<=(const string & s)const 
            {
               return !(*this > s);
            }
            bool operator>(const string & s)const 
            {
                return strcmp(_str,s._str)>0;
            }
            bool operator>=(const string & s)const 
            {
                return !(*this < s);
            }
            bool operator!=(const string & s)const 
            {
                return strcmp(_str,s._str)!=0;
            }
            void clear()
            {
                _size = 0;
                _str[_size] = 0;
            }
            size_t find(char ch,size_t pos = 0)const
            {
                for(size_t i = pos;i<_size;i++)
                {
                    if(_str[i]==ch)
                    {
                        return i;
                    }
                }
            }
            size_t find(const char* str,size_t pos = 0)const
            {
                const char* p = strstr(_str+pos,str);
                if(p)
                {
                    return (size_t)(p - _str);//
                }
                else
                {
                    return npos;
                }
            }
            string substr(size_t pos,size_t len = npos)const
            {
                string s;
                assert(_size>pos);
                if(len == npos || pos+len>=_size)
                {
                    len = _size - pos;
                    s.reserve(len);
                    for(size_t i = pos;i<_size;i++)
                    {
                        s += _str[i];
                    }
                }
                else
                {
                    s.reserve(len);
                    for(size_t i = pos;i<pos+len;i++)
                    {
                        s+= _str[i];
                    }
                } 
                return s;
            }
            void print()const
            {
                cout<<_str<<endl;
            }

        private:
        char* _str;
        size_t _size;
        size_t _capacity;
        const static size_t npos;//只有整形const变量在这里的静态变量
    };
    const size_t string :: npos = -1;

    ostream& operator<<(ostream& out,const string& s)
    {
        for(int i=0;i<s.size();i++)
        {
            out<<s[i];
        }
        return out;
    }
    istream& operator>>(istream& in,string& s)
    {
        // s.clear();
        // char t = 0;
        // t = in.get();
        // while(t!=' ' && t!= '\n')//涉及多次重扩展内存
        // {
        //     s.push_back(t);
        //     t = in.get();
        // }
        // return in;

        //利用缓冲区的思维
        s.clear();
        char arr[256];
        size_t i =0;
        char ch = in.get();
        while(ch != ' ' && ch!= '\n')
        {
            arr[i++] = ch;
            if(i == 255)
            {
                arr[i] = 0;
                s += arr;
                i = 0;
            }
            
            ch = in.get();
        }
        arr[i] = 0;
        s += arr;
        return in;
    }


    void Test_1()
    {
        string s("hello");
        for(int i =0;i<s.size();i++)
        {
            cout<<s[i]<<' ';
        }
        cout<<endl;
        string :: iterator it = s.begin();
        while(it != s.end())
        {
            cout<< *it++<<' ';
        }
        cout <<endl;
        for(auto ch :s)//本质调用迭代器
        {
            cout << ch <<' ';
        }
        
    }
    void Test_2()
    {
        string s1;
        s1.push_back('a');
        s1.push_back('b');
        s1.push_back('v');
        s1.push_back('d');
        s1.push_back('e');
        s1.push_back('f');
        s1.append(" hello");
        s1.insert(0,'&');
        s1.print();
        s1.insert(0,"123");
        s1.erase(3,5);
        s1.print();
    }
    void Test_3()
    {
        string s1 ("hello1");
        string s2 ("hello");
        string s4 = s1.substr(1,2);
        s4.print();
        cin >> s1;
    }
    void Test_4()
    {
        string s1("hi");
        string s2(s1);
        cout<< (void*)&s2[0]<<endl;
        cout<< (void*)&s1[0]<<endl;
        string s3("????");
        s2 = s3;
        cout<< (void*)&s2[0]<<endl;
        cout<< (void*)&s3[0]<<endl;
    }
    string GetTestStr()
    {
        string s = "dwefqerqf";
        s= "dwioenfo";
        cout<<&s<<endl;
        return s;
    }
    void Test_5()
    {
        //如下是不同编译器结果就会不同
        string s(GetTestStr());//经过测试，在g++编译器会做优化，直接把这个局部变量改了作用域和生命周期，使得不需要再调用析构，拷贝构造等函数
    //经过测试，再MSVC下（如VS2022，就不会做这个优化，这是G++编译在做的时候单独处理的
        cout<<&s;
        int c = 0;
    }
}